#include "scene/shadowspace.h"
#include "material/shadowmaterial.h"

CShadowSpace::CShadowSpace(){
    m_fShadowBias = 0.0f;
    m_fShadowRadius = 1.0f;
    m_vShadowMapSize[0] = 2048.0f;
    m_vShadowMapSize[1] = 2048.0f;
}
CShadowSpace::~CShadowSpace(){

}
bool32 CShadowSpace::Init( int32 nWidth, int32 nHeight ){
    m_rShadowMaterial = NEW CShadowMaterial();
    m_rShadowMaterial->Init();

    m_vShadowMapSize[0] = nWidth;
    m_vShadowMapSize[1] = nHeight;
    m_pTextureDepth = NEW CTextureTarget( nWidth, nHeight, True, False );

    float _fShadowLeft = -2048.0f;
    float _fShadowRight = 2048.0f;
    float _fShadowTop = 2048.0f;
    float _fShadowBottom = -2048.0f;
    float _fShadowNear = 0.0001f;
    float _fShadowFar = 4096.0f;

    SetViewPort( _fShadowLeft, _fShadowRight, _fShadowTop, _fShadowBottom, _fShadowNear, _fShadowFar );
    //SetPosition( 400, 150, 200 );
    SetDirectionPos( -500.0f, 1000.0f, 500.0f );
    SetPosition( 0, 0, 0 );

    return True;
}
bool32 CShadowSpace::Final(){

    return True;
}
void CShadowSpace::SetViewPort( float fLeft, float fRight, float fTop, float fBottom, float fNear, float fFar ){
    projectionMatrix.MakeOrthographic( fLeft, fRight, fTop, fBottom, fNear, fFar );
}

void CShadowSpace::BeginRender( int32 nViewportWidth, int32 nViewportHeight ){
    m_pTextureDepth->BeginRender( (int32)m_vShadowMapSize[0], (int32)m_vShadowMapSize[1] );
    Renderer_SetClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    Renderer_Clear( True, False );
    m_rShadowMaterial->Begin();
    m_rShadowMaterial->SetProjectionMatrix( projectionMatrix.m );
    m_rShadowMaterial->SetViewMatrix( matrixWorldInverse.m );

}
void CShadowSpace::EndRender(){
    m_rShadowMaterial->End();
    m_pTextureDepth->EndRender();
}
void CShadowSpace::Update(){
    //CVector3 _tView( 0, 0, 0 );
    CVector3 _tUp( 0, 1, 0 );
    viewMatrix.MakeLookAt( &m_tPosition, &n_tView, &_tUp );
    CQuaternion q;
    viewMatrix.GetRotationQuaternion( &q );
    CVector3 _tScale( 1, 1, 1 );
    worldMatrix.Compose( &m_tPosition, &q, &_tScale );
    worldMatrix.GetInverse( &matrixWorldInverse );
    CMatrix4::Multiply( &projScreenMatrix, &projectionMatrix, &matrixWorldInverse );

    // compute shadow matrix
    shadowMatrix.m[0] = 0.5f, shadowMatrix.m[1] = 0.0f, shadowMatrix.m[2] = 0.0f, shadowMatrix.m[3] = 0.0f,
        shadowMatrix.m[4] = 0.0f, shadowMatrix.m[5] = 0.5f, shadowMatrix.m[6] = 0.0f, shadowMatrix.m[7] = 0.0f,
        shadowMatrix.m[8] = 0.0f, shadowMatrix.m[9] = 0.0f, shadowMatrix.m[10] = 0.5f, shadowMatrix.m[11] = 0.0f,
        shadowMatrix.m[12] = 0.5f, shadowMatrix.m[13] = 0.5f, shadowMatrix.m[14] = 0.5f, shadowMatrix.m[15] = 1.0f;

    CMatrix4::Multiply( &shadowMatrix, &shadowMatrix, &projScreenMatrix );
}
//CShadowMaterial* CShadowSpace::GetShadowMaterial(){
//    return m_rShadowMaterial.GetEntityData();
//}
void CShadowSpace::SetPosition( float x, float y, float z ){
    m_tPosition.Set( x, y, z );
    Update();
}
void CShadowSpace::SetDirectionPos( float x, float y, float z ){
    m_tDirection.Set( x, y, z );
}
//Matrix4 CShadowSpace::GetShadowMatrix(){
//    return shadowMatrix.m;
//}
//CTextureTarget* CShadowSpace::GetShadowTexture(){
//    return m_pTextureDepth.GetEntityData();
//}

void CShadowSpace::Move( float x, float y, float z ){
    //m_tPosition
    n_tView.X = x; n_tView.Y = y; n_tView.Z = z;
    m_tPosition.X = x + m_tDirection.X; m_tPosition.Y = y + m_tDirection.Y; m_tPosition.Z = z + m_tDirection.Z;
}